
#include "DirWalker.h"

/* output error message m to stream str */
void DirWalker::desc_error(FILE* str, const char* m) {
    fprintf(str, m);
    fprintf(str, strerror(errno));
    fprintf(str, "\n");
}

void DirWalker :: do_file(string &path) {

	vector<string> *split_path = this->split(path);
	string result = "/";
	for (unsigned i = 0; i != split_path->size() - 1; i++){
		result += (*split_path)[i];
		result += "/";
	};
	result += "Files/";
	result += (*split_path)[split_path->size() - 1];
	delete split_path;
	if (fs->add_file(result) != 0)
		cout << "error: could not add file " << path 
			 << " to the repo;" << endl;
	// FIXME: content of the file is not copied

};

void DirWalker::do_dir(string &path) {

    vector<string> *split_path = this->split(path);
    string tag = (*split_path)[split_path->size() - 1];
    delete split_path;
    if (fs->add_dir(tag) != 0)
    	cout << "error: could not add tag " 
    		 << tag
    		 << " to the repo;" << endl;
    	
};

DirWalker :: DirWalker(FileSystem *fs){
	this->fs = fs;
};

int DirWalker::walk_dir(string &path) {
    vector<string> *split_path = this->split(path);
    string run_path = (*split_path)[split_path->size()-1];
    
    base_path = path.erase(path.length() - 1 - run_path.length());
    do_dir(run_path);
    return walk_dir_(run_path);
};


int DirWalker::walk_dir_(string &path) {
    DIR *dir = NULL;
    struct dirent *dir_desc = NULL;
    struct stat file_stat;
    string abs_path;
    string rel_path;

    abs_path = base_path + "/" + path;
    dir = opendir(abs_path.c_str());

    if (dir == NULL) {
	desc_error(INFOS, "Blad otwierania katalogu\n");
	return -1;
    }

    dir_desc = readdir(dir);
    
    while (dir_desc != NULL) {
	rel_path = string(dir_desc->d_name);
	rel_path = path + "/" + rel_path;
	abs_path = base_path + "/" + rel_path;
	stat(abs_path.c_str(), &file_stat);

	if ((rel_path.compare(rel_path.length() - string("/.").length(), 
			      rel_path.length(),
			      "/.") == 0) 
	    || (rel_path.compare(rel_path.length() - string("/..").length(),
				 rel_path.length(),
				 "/..") == 0)) {
	    /* olewamy . i .. */
	}
	else 
	if (S_ISREG(file_stat.st_mode)) {
	    do_file(rel_path);
	}
	else 
        if (S_ISDIR(file_stat.st_mode))  {
	    do_dir(rel_path);
	    walk_dir_(rel_path);
	}
	else {
	    /* nic nie robimy z plikami niezwyklymi */
	}
	dir_desc = readdir(dir);
    }

    /* dir_desc == NULL; blad czy eof? */
/*  // to chyba nie dziala dobrze
    if (errno != 0) {
	desc_error(INFOS, "Blad odczytu katalogu.\n");
	return -1;
    };
*/
    closedir(dir);

    return 0;
};

vector<string>* DirWalker :: split(const string &s){ 

    vector<string> *ret = new vector<string>; 
    string :: size_type i = 0;
    const char idle = '/';
	  
    while (i != s.size()){ 
		// First occurance of idle character - low bound 
		for (;i != s.size() && idle == s[i]; i++);
		string :: size_type j = i; 
		// Count until second occurance - high bound 
		for (; j != s.size() && idle != s[j]; j++);
		if (i != j) { 
		    // get string part from low to high bound index 
	    	ret->push_back(s.substr(i, j - i)); 
	    	i = j; 
		} 
    }

    return ret; 
};

